package com.tencent.wework;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.tencent.wework.entity.ImageMsg;
import com.tencent.wework.entity.TextMsg;
import org.apache.commons.codec.binary.Base64;
import sun.security.util.DerInputStream;
import sun.security.util.DerValue;

import javax.crypto.Cipher;
import java.io.File;
import java.io.FileOutputStream;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.util.Map;

public class FinanceTestDemo {
	
	 public static void main(String[] args) throws Exception {
		    args =new String[6];
		    args[0] = "1";
		    args[1] = "0";
		    args[2] = "20";
		    args[3] = "";
		    args[4] = "";
		    args[5] = "3";
		    
		    
	        long sdk = Finance.NewSdk();
	        System.out.println(Finance.Init(sdk, "ww4fe05e76c51b3891", "9V4Of91lIiA7Fno-i2R76SHr6-sq0M7W4hOuHOtlIv4"));
	        String priKey =
	            "-----BEGIN RSA PRIVATE KEY-----\n" +
	            "MIICXQIBAAKBgQCgpy6bm+wSzzA9RLVIfazCY9KgQ2qFxwiLbP00NpYZBl3CCh/X\n" +
	            "Kf3kzfVZKo8ITByo1Zh1zy9eC3mteKkskFFkTJW7FMBQPSJgTP/2k4oOoH5EJgt8\n" +
	            "1pkkGaCnUqJIWAqY31e1CSIcOJZE+Or3SA61/07zxB7YX6+Xzu2Om3e47wIDAQAB\n" +
	            "AoGAGXvrrMuDG0i6gj2P9DvbV8q18q4/C5GTDWrwj4PJM5cK8GjivCLxH4Z8UPSr\n" +
	            "U8mfEjkvwiBnhyeS2a22SFdsUZeN6+rxm+T8/Fs5uj7V8LULrBDdD3SkM6tmUanQ\n" +
	            "zzTliqou985+Q/IGApU5AagLPN352mcc7T3qSmuQYF/lEKECQQCsBviklQsjvp4m\n" +
	            "DkKUKByAEg2PCJtYOH3h7Ah47KfRvfdcYO+ipcr2k0xUOIHfyxNh2TRa4ff7+/Go\n" +
	            "Cwjzja99AkEA7xLcOURqdwp8HSQydPyAridu6xoebEMXgHKZhzRe4clwwtmQ9nDU\n" +
	            "2JGulzZ5tyPlXigFt0QO6OJtkUs6foJN2wJBAKOfUdpBRUIvaX8q6xq+eDU8dpcI\n" +
	            "ibFEsj8z4O8bsZemx2Ofc+7RIRadDenBgY5aOspD7S9QZS3Q+o5qSI5XwoUCQQCf\n" +
	            "MffjSmN6kUjEPu46aElnrmp1sxa/EI39wlHpbj4gK3sixK167PdOnvObTXMPOJ/r\n" +
	            "assjlfY3rU84iNeSlkIxAkBs+ON2dBdoxiUzMphlq1LJiaTlTkKEeZTyhTM3u1IJ\n" +
	            "OSwPOGP+btNI1jKBYTAPwWTqotbadkA4+tO1mzgLe1EO\n" +
	            "-----END RSA PRIVATE KEY-----\n";

			long ret = 0;

	        if (args[0].equals("1")) {
	            int seq = Integer.parseInt(args[1]);
	            int limit = Integer.parseInt(args[2]);
	            long slice = Finance.NewSlice();
	            ret = Finance.GetChatData(sdk, seq, limit, args[3], args[4], Integer.parseInt(args[5]), slice);
	            if (ret != 0) {
	                System.out.println("getchatdata ret " + ret);
	                return;
	            }

                //获取聊天信息列表
                String data = Finance.GetContentFromSlice(slice);

                JSONObject jsonObject = JSON.parseObject(data);
                JSONArray chatdata = jsonObject.getJSONArray("chatdata");
                for(int i=0;i<chatdata.size();i++) {
                    JSONObject chat = chatdata.getJSONObject(i);
                    String encrypt_random_key = chat.getString("encrypt_random_key");
                    String encrypt_chat_msg = chat.getString("encrypt_chat_msg");

                    //解密key
                    PrivateKey privateKey = getPrivateKey(priKey);
                    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
                    cipher.init(Cipher.DECRYPT_MODE, privateKey);
                    String key = new String(cipher.doFinal(Base64.decodeBase64(encrypt_random_key)));

                    long msgNum = Finance.NewSlice();
                    ret = Finance.DecryptData(sdk,key ,encrypt_chat_msg, msgNum);
                    if (ret != 0) {
                        System.out.println("getchatdata ret " + ret);
                        return;
                    }

                    //消息内容
                    String msg = Finance.GetContentFromSlice(msgNum);
                    JSONObject msgObj = JSON.parseObject(msg);
                    String msgtype = msgObj.getString("msgtype");

                    switch (msgtype) {
                        case "text":
                            //文本消息
                            TextMsg textMsg = JSONObject.toJavaObject(msgObj, TextMsg.class);
                            break;
                        case "image":
                            //图片消息
                            ImageMsg imageMsg = JSONObject.toJavaObject(msgObj, ImageMsg.class);
                            Map<String, Object> image = imageMsg.getImage();
                            String sdkfileid = image.get("sdkfileid").toString();

                            String indexbuf = "";
                            long media_data = Finance.NewMediaData();
                            ret = Finance.GetMediaData(sdk, indexbuf, sdkfileid, args[3], args[4], Integer.parseInt(args[5]), media_data);
                            System.out.println("getmediadata ret:" + ret);
                            if(ret!=0){
                                return;
                            }
                            System.out.printf("getmediadata outindex len:%d, data_len:%d, is_finis:%d\n",Finance.GetIndexLen(media_data),Finance.GetDataLen(media_data), Finance.IsMediaDataFinish(media_data));
                            try {
                                FileOutputStream outputStream  =new FileOutputStream(new File("d:\\fef.jpg"));
                                outputStream.write(Finance.GetData(media_data));
                                outputStream.close();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }

                            if(Finance.IsMediaDataFinish(media_data) == 1)
                            {
                                Finance.FreeMediaData(media_data);
                                break;
                            }
                            else
                            {
                                indexbuf = Finance.GetOutIndexBuf(media_data);
                                Finance.FreeMediaData(media_data);
                            }
                            break;
                        case "voice":
                            //语音
                            break;
                        case "video":
                            //视频
                            break;
                        case "card":
                            //名片
                            break;
                        case "location":
                            //位置
                            break;
                        case "emotion":
                            //表情
                            break;
                        case "file":
                            //文件
                            break;
                        case "link":
                            //链接
                            break;
                        case "weapp":
                            //小程序
                            break;
                        case "chatrecord":
                            //会话记录
                            break;

                    }

                    System.out.println("decrypt ret:" + ret + " msg:" + msg);
                    Finance.FreeSlice(msgNum);
                }

				System.out.println("getchatdata :" + data);
	            Finance.FreeSlice(slice);
	        } else if (args[0].equals("2")) {

				String indexbuf = "";
				while(true){
					long media_data = Finance.NewMediaData();
					ret = Finance.GetMediaData(sdk, indexbuf, args[1], args[2], args[3], Integer.parseInt(args[4]), media_data);
					System.out.println("getmediadata ret:" + ret);
					if(ret!=0){
						return;
					}
					System.out.printf("getmediadata outindex len:%d, data_len:%d, is_finis:%d\n",Finance.GetIndexLen(media_data),Finance.GetDataLen(media_data), Finance.IsMediaDataFinish(media_data));
	                try {
	                    FileOutputStream outputStream  =new FileOutputStream(new File("C:\\Users\\krosshuang\\Documents\\msgdata\\media_data"));
	                    outputStream.write(Finance.GetData(media_data));
	                    outputStream.close();
	                } catch (Exception e) {
	                    e.printStackTrace();
	                }

					if(Finance.IsMediaDataFinish(media_data) == 1)
					{
						Finance.FreeMediaData(media_data);
						break;
					}
					else
					{
						indexbuf = Finance.GetOutIndexBuf(media_data);
						Finance.FreeMediaData(media_data);
					}
																																				             }
	        }else if (args[0].equals("3")) {
				// notice!
				// // use prikey to decrpyt get args[1]
				
				long msg = Finance.NewSlice();
				ret = Finance.DecryptData(sdk,args[1] ,args[2], msg);
				if (ret != 0) {
				     System.out.println("getchatdata ret " + ret);
				         return;
				}
				System.out.println("decrypt ret:" + ret + " msg:" + Finance.GetContentFromSlice(msg));
				Finance.FreeSlice(msg);
			}
			else {
	            System.out.println("wrong args " + args[0]);
	        }
	        Finance.DestroySdk(sdk);
	    }

    public static PrivateKey getPrivateKey(String privKeyPEM) throws Exception{

        String privKeyPEMnew = privKeyPEM.replaceAll("\\n", "").replace("-----BEGIN RSA PRIVATE KEY-----", "").replace("-----END RSA PRIVATE KEY-----", "");
        byte[] bytes = java.util.Base64.getDecoder().decode(privKeyPEMnew);

        DerInputStream derReader = new DerInputStream(bytes);
        DerValue[] seq = derReader.getSequence(0);
        BigInteger modulus = seq[1].getBigInteger();
        BigInteger publicExp = seq[2].getBigInteger();
        BigInteger privateExp = seq[3].getBigInteger();
        BigInteger prime1 = seq[4].getBigInteger();
        BigInteger prime2 = seq[5].getBigInteger();
        BigInteger exp1 = seq[6].getBigInteger();
        BigInteger exp2 = seq[7].getBigInteger();
        BigInteger crtCoef = seq[8].getBigInteger();

        RSAPrivateCrtKeySpec keySpec = new RSAPrivateCrtKeySpec(modulus, publicExp, privateExp, prime1, prime2, exp1, exp2, crtCoef);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }

}
